package com.xw.musicplayer.engine;

import android.content.Context;
import android.media.AudioAttributes;
import android.media.MediaPlayer;
import android.net.Uri;
import android.text.TextUtils;

import java.io.IOException;
import java.lang.ref.WeakReference;

/**
 * 系统播放器.
 */
public class SystemMediaPlayer extends AbstractMediaPlayer {

    private MediaPlayer mInternalMediaPlayer;
    private SystemMediaPlayerListenerHolder mInternalListenerAdapter;
    private String mDataSource;

    @Override
    public void init(Context context) {
        AudioAttributes aat = new AudioAttributes.Builder()
                .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
                .build();
        mInternalMediaPlayer = new MediaPlayer();
        mInternalMediaPlayer.setAudioAttributes(aat);

        mInternalListenerAdapter = new SystemMediaPlayerListenerHolder(this);
        attachInternalListeners();

    }

    @Override
    public void prepareAsync() throws IllegalArgumentException {
        mInternalMediaPlayer.prepareAsync();
    }

    @Override
    public void release() {
        mInternalMediaPlayer.release();
        resetListeners();
        attachInternalListeners();
    }

    @Override
    public void start() throws IllegalStateException {
        mInternalMediaPlayer.start();
    }

    @Override
    public void stop() throws IllegalStateException {
        mInternalMediaPlayer.stop();
    }

    @Override
    public void pause() throws IllegalStateException {
        mInternalMediaPlayer.pause();
    }

    @Override
    public void reset() {
        try {
            mInternalMediaPlayer.reset();
        } catch (IllegalStateException e) {
        }
        attachInternalListeners();
    }

    @Override
    public String getDataSource() {
        return mDataSource;
    }

    @Override
    public void setDataSource(String path) throws IOException, IllegalArgumentException, SecurityException, IllegalStateException {
        mDataSource = path;
        Uri uri = Uri.parse(path);
        String scheme = uri.getScheme();
        if (!TextUtils.isEmpty(scheme) && scheme.equalsIgnoreCase("file")) {
            mInternalMediaPlayer.setDataSource(uri.getPath());
        } else {
            mInternalMediaPlayer.setDataSource(path);
        }
    }

    @Override
    public boolean isPlaying() {
        try {
            return mInternalMediaPlayer.isPlaying();
        } catch (IllegalStateException e) {
            return false;
        }
    }

    @Override
    public void seekTo(long milliseconds) throws IllegalStateException {
        mInternalMediaPlayer.seekTo((int) milliseconds);
    }

    @Override
    public long getCurrentPosition() {
        if (mInternalMediaPlayer != null) {
            return mInternalMediaPlayer.getCurrentPosition();
        } else {
            return 0;
        }
    }

    @Override
    public long getDuration() {
        if (mInternalMediaPlayer != null) {
            return mInternalMediaPlayer.getDuration();
        } else {
            return 0;
        }
    }

    private void attachInternalListeners() {
        mInternalMediaPlayer.setOnPreparedListener(mInternalListenerAdapter);
        mInternalMediaPlayer
                .setOnBufferingUpdateListener(mInternalListenerAdapter);
        mInternalMediaPlayer.setOnCompletionListener(mInternalListenerAdapter);
        mInternalMediaPlayer
                .setOnSeekCompleteListener(mInternalListenerAdapter);
        mInternalMediaPlayer.setOnErrorListener(mInternalListenerAdapter);
        mInternalMediaPlayer.setOnInfoListener(mInternalListenerAdapter);
    }

    private class SystemMediaPlayerListenerHolder implements
            MediaPlayer.OnPreparedListener,
            MediaPlayer.OnCompletionListener,
            MediaPlayer.OnBufferingUpdateListener,
            MediaPlayer.OnSeekCompleteListener,
            MediaPlayer.OnErrorListener,
            MediaPlayer.OnInfoListener {

        private final WeakReference<SystemMediaPlayer> mWeakMediaPlayer;

        public SystemMediaPlayerListenerHolder(SystemMediaPlayer mp) {
            mWeakMediaPlayer = new WeakReference<>(mp);
        }

        @Override
        public boolean onInfo(MediaPlayer mp, int what, int extra) {
            SystemMediaPlayer self = mWeakMediaPlayer.get();
            return self != null && notifyOnInfo(what, extra);

        }

        @Override
        public boolean onError(MediaPlayer mp, int what, int extra) {
            SystemMediaPlayer self = mWeakMediaPlayer.get();
            return self != null && notifyOnError(what, extra);

        }

        @Override
        public void onSeekComplete(MediaPlayer mp) {
            SystemMediaPlayer self = mWeakMediaPlayer.get();
            if (self == null) {
                return;
            }
            notifyOnSeekComplete();
        }

        @Override
        public void onBufferingUpdate(MediaPlayer mp, int percent) {
            SystemMediaPlayer self = mWeakMediaPlayer.get();
            if (self == null) {
                return;
            }
            notifyOnBufferingUpdate(percent);
        }

        @Override
        public void onCompletion(MediaPlayer mp) {
            SystemMediaPlayer self = mWeakMediaPlayer.get();
            if (self == null) {
                return;
            }
            notifyOnCompletion();
        }

        @Override
        public void onPrepared(MediaPlayer mp) {
            SystemMediaPlayer self = mWeakMediaPlayer.get();
            if (self == null) {
                return;
            }
            notifyOnPrepared();
        }
    }

}
